package com.study.graph.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.*;

public class StrUtil {

    /***
     * 压缩GZip
     *
     * @param data
     * @return
     */
    public static byte[] gZip(byte[] data) {
        byte[] b = null;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            GZIPOutputStream gzip = new GZIPOutputStream(bos);
            gzip.write(data);
            gzip.finish();
            gzip.close();
            b = bos.toByteArray();
            bos.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return b;
    }

    /***
     * 解压GZip
     *
     * @param data
     * @return
     */
    public static byte[] unGZip(byte[] data) {
        byte[] b = null;
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(data);
            GZIPInputStream gzip = new GZIPInputStream(bis);
            byte[] buf = new byte[1024];
            int num = -1;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((num = gzip.read(buf, 0, buf.length)) != -1) {
                baos.write(buf, 0, num);
            }
            b = baos.toByteArray();
            baos.flush();
            baos.close();
            gzip.close();
            bis.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return b;
    }



    /***
     * 压缩Zip
     *
     * @param data
     * @return
     */
    public static byte[] zip(byte[] data) {
        byte[] b = null;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ZipOutputStream zip = new ZipOutputStream(bos);
            ZipEntry entry = new ZipEntry("zip");
            entry.setSize(data.length);
            zip.putNextEntry(entry);
            zip.write(data);
            zip.closeEntry();
            zip.close();
            b = bos.toByteArray();
            bos.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return b;
    }

    /***
     * 解压Zip
     *
     * @param data
     * @return
     */
    public static byte[] unZip(byte[] data) {
        byte[] b = null;
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(data);
            ZipInputStream zip = new ZipInputStream(bis);
            while (zip.getNextEntry() != null) {
                byte[] buf = new byte[1024];
                int num = -1;
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                while ((num = zip.read(buf, 0, buf.length)) != -1) {
                    baos.write(buf, 0, num);
                }
                b = baos.toByteArray();
                baos.flush();
                baos.close();
            }
            zip.close();
            bis.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return b;
    }

    /***
     * 压缩BZip2
     *
     * @param data
     * @return
     */
    public static byte[] bZip2(byte[] data) {
//        byte[] b = null;
//        try {
//            ByteArrayOutputStream bos = new ByteArrayOutputStream();
//            CBZip2OutputStream bzip2 = new CBZip2OutputStream(bos);
//            bzip2.write(data);
//            bzip2.flush();
//            bzip2.close();
//            b = bos.toByteArray();
//            bos.close();
//        } catch (Exception ex) {
//            ex.printStackTrace();
//        }
//        return b;
        return null;
    }

    /***
     * 解压BZip2
     *
     * @param data
     * @return
     */
    public static byte[] unBZip2(byte[] data) {
        byte[] b = null;
//        try {
//            ByteArrayInputStream bis = new ByteArrayInputStream(data);
//            CBZip2InputStream bzip2 = new CBZip2InputStream(bis);
//            byte[] buf = new byte[1024];
//            int num = -1;
//            ByteArrayOutputStream baos = new ByteArrayOutputStream();
//            while ((num = bzip2.read(buf, 0, buf.length)) != -1) {
//                baos.write(buf, 0, num);
//            }
//            b = baos.toByteArray();
//            baos.flush();
//            baos.close();
//            bzip2.close();
//            bis.close();
//        } catch (Exception ex) {
//            ex.printStackTrace();
//        }
        return b;
    }

    /**
     * 把字节数组转换成16进制字符串
     *
     * @param bArray
     * @return
     */
    public static String bytesToHexString(byte[] bArray) {
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }


    /**
     *jzlib 压缩数据
     *
     * @param object
     * @return
     * @throws IOException
     */
    /*
    public static byte[] jzlib(byte[] object) {
        byte[] data = null;
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ZOutputStream zOut = new ZOutputStream(out,
                    JZlib.Z_DEFAULT_COMPRESSION);
            DataOutputStream objOut = new DataOutputStream(zOut);
            objOut.write(object);
            objOut.flush();
            zOut.close();
            data = out.toByteArray();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
    */
    /**
     *jzLib压缩的数据
     *
     * @return
     * @throws IOException
     */
    /*
    public static byte[] unjzlib(byte[] object) {
        byte[] data = null;
        try {
            ByteArrayInputStream in = new ByteArrayInputStream(object);
            ZInputStream zIn = new ZInputStream(in);
            byte[] buf = new byte[1024];
            int num = -1;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((num = zIn.read(buf, 0, buf.length)) != -1) {
                baos.write(buf, 0, num);
            }
            data = baos.toByteArray();
            baos.flush();
            baos.close();
            zIn.close();
            in.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
    */

    public static void main(String[] args) {
        String s = "this is a test"+"1、一般来说要实现压缩，那么返回方式一般是用byte[]数组。\n" +
                "\n" +
                "2、研究发现byte[]数组在转成可读的String时，大小会还原回原来的。\n" +
                "\n" +
                "3、如果采用压缩之后不可读的String时，互相转换大小会变小，唯一缺点就是转出的String不可读，需要再次解码之后才可读。\n" +
                "\n" +
                "4、对于压缩一般最近常听的应该就是gzip这些。";
        byte[] b0 = s.getBytes(StandardCharsets.UTF_8);
        System.out.println("b0:"+b0.length);
        byte[] b1 = zip(s.getBytes(StandardCharsets.UTF_8));
        System.out.println("zip:" + b1.length);
        //System.out.println("zip:" + bytesToHexString(b1));
        byte[] b2 = unZip(b1);
        //System.out.println("unZip:" + new String(b2));
        byte[] b3 = bZip2(s.getBytes());
        System.out.println("bZip2:" + b1.length);
        //System.out.println("bZip2:" + bytesToHexString(b3));
        byte[] b4 = unBZip2(b3);
        //System.out.println("unBZip2:" + new String(b4));
        byte[] b5 = gZip(s.getBytes());
        System.out.println("gzip:" + b5.length);
        byte[] b6 = unGZip(b5);
        System.out.println("ungzip:" + new String(b6));
        //byte[] b7 = jzlib(s.getBytes());
        //System.out.println("jzlib:" + bytesToHexString(b7));
        //byte[] b8 = unjzlib(b7);
        //System.out.println("unjzlib:" + new String(b8));
    }

}
